<!DOCTYPE HTML>
<html>
<head>
<meta charset=utf8>
<script src="../resources/js-test.js"></script>
<style>
    @supports (width: 0) {
        s { width: 0; }
        @supports (width: 1) {
            s { color: #000; }
            @import url("../fast/cssom/resources/import.css");
            @charset "UTF-8";
            @namespace "";
        }
    }

    @supports  ((  (     padding: 0)    and (display: none)) or (display: rainbow))  {
        dfn { width:0; }

        @supports (width: 0) {
            br { height:0; }
        }

        /* Rules with syntax errors should be ignored. */
        @supports (display: none);
        @supports (display: none)) ;
        @supports;
        @supports ;
        @supports (display: none)) {}
        @supports (display: )) {}
        @supports ((display: none) and {}
        @supports (display: none) {}
        );
        @supports ((display: none) and ;
        @supports (display: none) {}
        );

        ol { display:none; }
    }

    @media all {
        @supports  ( padding: 0) {
            @page :left { top: 0 }
        }
    }

    @supports (border: black) and (padding: 0) and (width: 0) {
        dfn { width:0; }
    }
</style>
</head>
<body>
<script>
    description("Test CSSSupportRule.");


    shouldBeDefined("CSSRule.SUPPORTS_RULE");

    evalAndLog("rules = document.styleSheets[1].cssRules");
    shouldEvaluateTo("rules.length", 4);
    shouldBeType("rules[0]", "CSSSupportsRule");
    shouldBe("rules[0].type", "CSSRule.SUPPORTS_RULE");
    shouldEvaluateTo("rules[0].cssRules.length", 2);
    shouldBe("rules[0].cssRules[0].type", "CSSRule.STYLE_RULE");
    shouldBeType("rules[0].cssRules[1]", "CSSSupportsRule");
    shouldBe("rules[0].cssRules[1].type", "CSSRule.SUPPORTS_RULE");
    shouldEvaluateTo("rules[0].cssRules[1].cssRules.length", 1);
    shouldBe("rules[0].cssRules[1].cssRules[0].type", "CSSRule.STYLE_RULE");
    shouldBeEqualToString("rules[0].conditionText", "(width: 0)");
    shouldBeEqualToString("rules[0].cssText",
                          "@supports (width: 0) {\n" +
                          "  s { width: 0px; }\n" +
                          "  @supports (width: 1) {\n" +
                          "  s { color: rgb(0, 0, 0); }\n" +
                          "}\n" +
                          "}");

    debug("\nMissing argument exceptions.");
    shouldThrow("rules[0].insertRule()");
    shouldThrow("rules[0].insertRule('@media all {}')");
    shouldThrow("rules[0].deleteRule()");

    debug("\nInserting and deleting rules.");
    evalAndLog("rules[0].insertRule('@media all { #s { width: 0px; } }', 2)");
    shouldEvaluateTo("rules[0].cssRules.length", 3);
    shouldBe("rules[0].cssRules[2].type", "CSSRule.MEDIA_RULE");
    evalAndLog("rules[0].deleteRule(2)");
    shouldEvaluateTo("rules[0].cssRules.length", 2);

    evalAndLog("rules[0].cssRules[1].insertRule('@supports (display: rainbow) {}', 1)");
    shouldEvaluateTo("rules[0].cssRules[1].cssRules.length", 2);
    shouldBeType("rules[0].cssRules[1].cssRules[1]", "CSSSupportsRule");
    shouldBe("rules[0].cssRules[1].cssRules[1].type", "CSSRule.SUPPORTS_RULE");
    evalAndLog("rules[0].cssRules[1].deleteRule(1)");
    shouldEvaluateTo("rules[0].cssRules.length", 2);

    debug("\n@charset, @namespace, @import rules are not allowed inside @supports.")
    shouldThrow("rules[0].insertRule('@charset \"UTF-8\"', 2)", '"SyntaxError: Failed to execute \'insertRule\' on \'CSSSupportsRule\': the rule \'@charset \\"UTF-8\\"\' is invalid and cannot be parsed."');
    shouldThrow("rules[0].insertRule('@namespace \"\"', 2)", '"SyntaxError: Failed to execute \'insertRule\' on \'CSSSupportsRule\': the rule \'@namespace \\"\\"\' is invalid and cannot be parsed."');
    shouldThrow("rules[0].insertRule('@import url(\"../fast/cssom/resources/import.css\")', 2)", '"HierarchyRequestError: Failed to execute \'insertRule\' on \'CSSSupportsRule\': \'@import\' rules cannot be inserted inside a group rule."');


    debug("\nWhitespace and formatting should be preserved within the condition, whitespace outside the condition should be trimmed.");
    shouldBeEqualToString("rules[1].conditionText", "((  (     padding: 0)    and (display: none)) or (display: rainbow))");


    debug("\n@supports rule nested inside a media rule.");
    shouldBe("rules[2].type", "CSSRule.MEDIA_RULE");
    shouldEvaluateTo("rules[2].cssRules.length", 1);
    shouldBeType("rules[2].cssRules[0]", "CSSSupportsRule");
    shouldBe("rules[2].cssRules[0].type", "CSSRule.SUPPORTS_RULE");
    shouldBeEqualToString("rules[2].cssRules[0].conditionText", "( padding: 0)");
    shouldEvaluateTo("rules[0].cssRules[1].cssRules.length", 1);
    shouldBe("rules[2].cssRules[0].cssRules[0].type", "CSSRule.PAGE_RULE");
    shouldBeEqualToString("rules[2].cssText",
                          "@media all { \n" +
                          "  @supports ( padding: 0) {\n" +
                          "  @page :left { top: 0px; }\n" +
                          "}\n" +
                          "}");


    debug("\nNo extra parens should be added to the conditionText.");
    shouldBeEqualToString("rules[3].conditionText", "(border: black) and (padding: 0) and (width: 0)");


    debug("\nDeleting a top-level rule should work correctly.");
    evalAndLog("document.styleSheets[1].deleteRule(3)");
    shouldEvaluateTo("rules.length", 3);
    shouldBe("rules[0].type", "CSSRule.SUPPORTS_RULE");
    shouldEvaluateTo("rules[0].cssRules.length", 2);
    shouldBe("rules[0].cssRules[0].type", "CSSRule.STYLE_RULE");
    shouldBe("rules[0].cssRules[1].type", "CSSRule.SUPPORTS_RULE");
    shouldEvaluateTo("rules[0].cssRules[1].cssRules.length", 1);
    shouldBe("rules[0].cssRules[1].cssRules[0].type", "CSSRule.STYLE_RULE");

</script>
</body>
</html>

